export default {}
const tesla = ['tesla', 'model 3', 'model X', 'model Y'] as const


// 获取数组长度
type Length<T extends readonly any[]> = T['length'];
// type Length<T> = T extends readonly any[] ? T['length'] : never

//❗️缺点：
// 不能精确推导只读元组（例如 as const 后的数组）除非手动加 readonly。
// 不能限制必须传入数组，传入其他类型会 fallback 到 never，但不会在编译期报错。
type asdsa = Length<typeof tesla>
type asd22sa = typeof tesla[number]


type A = Length<[1, 2, 3]>


type MyExclude<T, U extends keyof T> = T extends U ? never : T


// @ts-ignore
type cases =
    MyExclude<'a' | 'b' | 'c', 'b'>

// 假如我们有一个 Promise 对象，这个 Promise 对象会返回一个类型。在 TS 中，我们用 Promise 中的 T 来描述这个 Promise 返回的类型。请你实现一个类型，可以获取这个类型。
// 🔍 TypeScript 的 Promise<T> 定义（简化版）
// TypeScript 内置的 Promise<T> 是个接口类型，类似这样：
interface Promise<T> {
    then<TResult1 = T, TResult2 = never>(
        onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null | undefined,
        onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined
    ): Promise<TResult1 | TResult2>
}


type MyAwaited<T> = T extends null | undefined ? T :
    T extends object & { then(onfulfilled: infer F, ...args: any): any }
        ? F extends (value: infer V, ...args: any) => any
            ? MyAwaited<V>
            : never
        : T
type Y = Promise<{ field: number }>

type Result = MyAwaited<Y>
type X = Promise<string>
type Z = Promise<Promise<string | number>>
type T = { then: (onfulfilled: (arg: number) => any) => any }


let adsda: T = {
    then(onfulfilled: (arg: number) => any): any {
        onfulfilled(1)
    }

}

// 实现建议的contact
type Concat<T extends readonly unknown[], U extends readonly unknown[]> = [...T, ...U]

const tuple = [1] as const

type cases222 = Concat<[1, 2], [3, 4]>

// 在类型系统里实现 JavaScript 的 Array.includes 方法，这个类型接受两个参数，返回的类型要么是 true 要么是 false。
type Includes<T extends readonly any[], U> =
    T extends [infer First, ...infer Rest]
        ? Equal<First, U> extends true
            ? true
            : Includes<Rest, U>
        : false


type cases333 = Includes<[1, 2, 3], 3>

type asdsad = Includes<[1 | 2], 1>

let adsad: asdsad


// 只读   对象部分属性只读
// https://www.typescriptlang.org/play/?ssl=42&ssc=2&pln=38&pc=1#code/PQKgUABBAcELQUJ-ahDGMBcJgwJUHo6hyA0FfKhv6MnjhNKICMBPCAQQDsAXACwHs7qAxAVwgAoABAIaMAZlwCUEAMSBaOUCS3tIBOAU0EATNgBtqUluQBWygMYM4Aa2WUAzmCJT7EQBkZgO7dbUQHnagBudAAHKAqOUDbNoDR6gAGALKUAEqqGnTaAEwAPAAqADQQANIAfMGAMP+AwdqAZHqAkOaAJHKAs56A3j6BgCFugEPKgA6mwUnBgDEqwenBgEAMbhBVEO3BEIDgxoBZ2v3NEDKAgZGA1RGAfdGAdv6AXHIEfCrqWpSS1TidgEGagDnmgFTmgAvGgNnyAzmAmEqAKXqA-vKAAkZFOIC-CYAbyiv4OYCMOoDzCoB2ZoAsBOqwSiG1ilGS2W8gHYLbpEQDR8nsesFUQwbFAAJaMZSKESCIzKCBJFgaCAAbyIUAYmIYmmUAC4IFYGIpsQBzKkQNTKKxGNkABxpbCZLLZdE5UCgRhYAFsBfSGMo1EzyCwWPThEQAL49GV0FkQBiklhM8JgmLxZImtIAchpdOUtogAB8ILaeXzBcK6LbMhAALwUrkO+lMgBEAAlLOGUlzPfzMULMSKIOGROryIJFLGuTL5YrlUz8ZorMo41BdURjRoAHSholBqPKTSaFjhiDAYAQACiikULEUTKMwjoLAYEHWVismPZdAggkn0U2EAFA4FuIYlGrJtrCe9KfnTazig46o7Xd7-cHw9H46Xgmns-ni-Wluoa5YG8UW53dfzCrKEqaiBkaihcESl4APLpEQqLBD0-qABTqEAAOK0kwXDkBAgBQcoAp+aANDugBY-0wDAMAKVgMl26JGEwtb6FYtaDuywDQMAABeTBwAAwgAcmAIDALYoAQAA+uJEmSRJECAAby1SAMdygCAHmJUmqaJECCbYYBbhuEDmsuEKJKkGQQMoAAeSp0GoVgQBYlAsCIxKgXZDnEv6QaUlAADaAAKEDYrZliuUkC42X55mWdZJkAPwQHQygAG64hATI+QAukySS+WlYDahAABkwZQG+K6+f587pBlxLZblYAiWpqkQIA0raAKvRgAUrgiKkNdJmmYvKg4TjpRLkrQmiYhYaQ9mZG4mBAeUiAOsruvwQ1wLRgitsoEq8sAXA0qWtq2ENEAjmWNlBl5RBTTNDAJDQY0WAk+nglaJIaAAjJkaQWps1ofZkAMVr203GLd93jcoT2RAZr0mu9doNs6boeryibJmwfqTSDJjKoDV3Y2DD2Q8975GSacQI7S9JI+6+5Jj6mPAzduNffjN13UTUM-YZf0sBTtOoweGMQF9TOgyzcY5XV3YrVYcDmTd8vXoo2mULpuIDoooEk5sZMfZTjo07a2IJRtmJqH6tjYkqeIEkSb0sO9RVGlTjLMqyHJEHT6N0NFooexKRAAYWKoQGqGqqHQtVgNbuL4oSxLk87JUQi7jr++KkrcoL9OHn77uZ0HcqAcBqrqpqUdVrHtsJ9d4sgZ5D7vmnYYF57xUw9Q3s+vnYrtydxch2XEdalW9XddJgDQct4gCm1l1E8aUJoBEP66CANVycmAMeRgAq3iRZEUVRwA0XRDFMYoLFscIVgAO64hxXF8SvECETve-kZR1F8ifjHMaxwBWBqPah4MQiwgIAF7NABYmi4N+B9P60Xoj-c+98eL8U0kAA
type MyReadonly2<T, K extends keyof T = keyof T> = {
    [P in keyof T as P extends K ? never : P]: T[P]
} & {
    readonly [P in K]: T[P]
}

type MyReadonly3<T, K extends keyof T = keyof T> = Omit<T, K> & Readonly<Pick<T, K>>


// 深层拷贝
type DeepReadonly<T> = T extends (...args: any[]) => any
    ? T
    : T extends object
        ? {
            readonly [P in keyof T]: DeepReadonly<T[P]>
        }
        : T


type X1 = {
    a: () => 22
    b: string
    c: {
        d: boolean
        e: {
            g: {
                h: {
                    i: true
                    j: 'string'
                }
                k: 'hello'
            }
            l: [
                'hi',
                {
                    m: ['hey']
                },
            ]
        }
    }
}
type X2 = { a: string } | { b: number }
type dasad = DeepReadonly<X2>
type dasadsada = DeepReadonly<X1>

// 可串联构造器
type Chainable<T extends object = {}> = {
    option<K extends string, V>(key: K, value: V): Chainable<Omit<T, K> & { [P in K]: V }>
    get(): T

}


// Chainable 是带泛型参数的接口，T 代表当前累积的对象类型，默认初始是空对象 {}。
// option 函数：
// key: K 是新加入的键，限制为 string。
// value: V 是该键对应的值类型。
// 返回一个新的 Chainable，类型是 Omit<T, K> & { [P in K]: V }，即先去掉已有类型中同名键（覆盖旧值），然后加上新属性。
// get() 返回当前累积的类型 T。
// { [P in K]: V }>  V的类型能自动推出
declare const config: Chainable

const result = config
    .option('foo', 123)
    .option('name', 'type-challenges')
    .option('bar', {value: 'Hello World'})
    .get()

// 实现一个Last<T>泛型，它接受一个数组T并返回其最后一个元素的类型。
type Last<T extends readonly any[]> = T extends [...infer Rest, infer last] ? last : never

// 实现一个First<T>泛型，它接受一个数组T并返回它的第一个元素的类型。
type First<T extends readonly any[]> = T extends [infer First, ...infer Rest,] ? First : never


// 实现 TrimLeft<T> ，它接收确定的字符串类型并返回一个新的字符串，其中新返回的字符串删除了原字符串开头的空白字符串。
type WhiteSpace = ' ' | '\n' | '\t'
type TrimLeft<S extends string> =
    S extends `${WhiteSpace}${infer Rest}`
        ? TrimLeft<Rest>
        : S


// 实现 Capitalize<T> 它将字符串的第一个字母转换为大写，其余字母保持原样。
type MyCapitalize<T extends string> = T extends `${infer First}${infer Rest}` ? `${Uppercase<First>}${Rest}` : T

// 实现 Replace<S, From, To> 将字符串 S 中的第一个子字符串 From 替换为 To 。
type Replace<S extends string, From extends string, To extends string> = From extends '' ? S
    : S extends `${infer Rest}${From}${infer lAST}` ? `${Rest}${To}${lAST}` : S


type ReplaceAll<S extends string, From extends string, To extends string> =
    From extends '' ? S :
        S extends `${infer Prefix}${From}${infer Suffix}`
            ? `${Prefix}${To}${ReplaceAll<Suffix, From, To>}`
            : S

// 实现一个泛型 AppendArgument<Fn, A>，对于给定的函数类型 Fn，以及一个任意类型 A，返回一个新的函数 G。G 拥有 Fn 的所有参数并在末尾追加类型为 A 的参数。
type AppendArgument<Fn, A> = Fn extends (...args: infer Rest) => infer R
    ? (...args: [...Rest, A]) => R
    : never

type Case1 = AppendArgument<(a: number, b: string) => number, boolean>

// 实现联合类型的全排列，将联合类型转换成所有可能的全排列数组的联合类型。
type Permutation<T, K = T> =
    [T] extends [never]
        ? []
        : T extends any
            ? [T, ...Permutation<Exclude<K, T>>]
            : never
type z2zz = Permutation<'A' | 'B' | 'C'>

// 计算字符串的长度，类似于 String#length 。
type LengthOfString<S extends string, Arr extends readonly any[] = []> = S extends `${infer First}${infer Rest}`
    ? LengthOfString<Rest, [First, ...Arr]>
    : Arr['length']


type sadasd = LengthOfString<'kumiko'>


// 在这个挑战中，你需要写一个接受数组的类型，并且返回扁平化的数组类型。
type Flatten<T extends any[], K extends readonly any[] = []> = T extends [infer A, ...infer Rest]
    ? A extends any[]
        ? Flatten<[...A, ...Rest], K>  // 展开 A 再处理剩余的
        : Flatten<Rest, [...K, A]>     // 非数组则直接推入结果
    : K


type AppendToObject<T, K extends keyof any, V> = {
    [P in keyof T | K]: P extends keyof T ? T[P] : V
}

type test1 = {
    key: 'cat'
    value: 'green'
}

type case1 = AppendToObject<test1, 'home', boolean>


type zks = "-" | "_" | "n"
type Absolute<T extends number | string | bigint> =
    `${T}` extends `${zks}${infer Rest}`
        ? Absolute<Rest>
        : `${T}` extends `${infer First}${infer Rest}`
            ? `${First}${Absolute<Rest>}`
            : ''

